package com.adcc.soundalarm.config.system;

import com.adcc.soundalarm.common.Constant;
import com.adcc.soundalarm.common.Log;
import org.apache.log4j.PropertyConfigurator;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;

import java.io.*;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by ZHANG on 2017/2/9.
 */
public class AppConfiguration {

    private AlarmFactory alarmFactory;

    private AppConfiguration(){}

    /**
     * 静态内部类
     */
    private static class LazyHolder{
        private static final AppConfiguration INSTANCE = new AppConfiguration();
    }

    /**
     * 单例方法
     * */
    public synchronized static AppConfiguration getInstance() {
        return LazyHolder.INSTANCE;
    }

    public AlarmFactory getAlarmFactory() {
        return alarmFactory;
    }

    public void setAlarmFactory(AlarmFactory alarmFactory) {
        this.alarmFactory = alarmFactory;
    }

    /**
     * 配置加载
     */
    public void init(){
        BufferedReader br = null;
        try{
            PropertyConfigurator.configure(System.getProperty("user.dir")+File.separator+"conf"+File.separator+"log4j.properties");
            br=new BufferedReader(new InputStreamReader(new FileInputStream(System.getProperty("user.dir")+File.separator+"conf"+File.separator+"conf.yml"),"UTF-8"));
            DumperOptions dumperOptions = new DumperOptions();
            dumperOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
            dumperOptions.setDefaultScalarStyle(DumperOptions.ScalarStyle.PLAIN);
            dumperOptions.setLineBreak(DumperOptions.LineBreak.UNIX);
            Yaml yaml = new Yaml(dumperOptions);
            AppConfiguration appConfiguration = yaml.loadAs(br,AppConfiguration.class);
            this.setAlarmFactory(appConfiguration.getAlarmFactory());
        }catch (Exception e){
            Log.error("AppConfiguration init error!", e);
        }finally {
            try {
                if(br != null) {
                    br.close();
                }
            } catch (IOException ex) {
                Log.error("close io error", ex);
            }
        }
    }

    /**
     * 更新配置文件
     * @param newMap
     * @return
     */
    public boolean updateConfigSetting(Map<String,Object> newMap){
        FileWriter fw = null;
        FileInputStream fis = null;
        boolean result = false;
        String path = System.getProperty("user.dir")+"/conf/conf.yml";
        try {
            // 将json串转换成Map
            fis = new FileInputStream(new File(path));
            DumperOptions options = new DumperOptions();
            options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
            options.setDefaultScalarStyle(DumperOptions.ScalarStyle.PLAIN);
            options.setLineBreak(DumperOptions.LineBreak.UNIX);
            Yaml yaml = new Yaml(options);
            Map<String,Object> oldMap = yaml.loadAs(fis, HashMap.class);
            if(oldMap.get("alarmFactory") !=null){
                Map<String,Object>  alarmMap = (HashMap)oldMap.get("alarmFactory");
                if(alarmMap.get(Constant.ALARM_UPDATE_CONFIG_PATH) !=null && newMap.get(Constant.ALARM_UPDATE_CONFIG_PATH)!=null){
                    alarmMap.put(Constant.ALARM_UPDATE_CONFIG_PATH,newMap.get(Constant.ALARM_UPDATE_CONFIG_PATH));
                }
                if(alarmMap.get(Constant.ALARM_UPDATE_CONFIG_LOG_URI) !=null && newMap.get(Constant.ALARM_UPDATE_CONFIG_LOG_URI)!=null){
                    alarmMap.put(Constant.ALARM_UPDATE_CONFIG_LOG_URI,newMap.get(Constant.ALARM_UPDATE_CONFIG_LOG_URI));
                }
                if(alarmMap.get(Constant.ALARM_UPDATE_CONFIG_USER_URI) !=null && newMap.get(Constant.ALARM_UPDATE_CONFIG_USER_URI)!=null){
                    alarmMap.put(Constant.ALARM_UPDATE_CONFIG_USER_URI,newMap.get(Constant.ALARM_UPDATE_CONFIG_USER_URI));
                }
                if(alarmMap.get(Constant.ALARM_UPDATE_CONFIG_STATE_URI) !=null && newMap.get(Constant.ALARM_UPDATE_CONFIG_STATE_URI)!=null){
                    alarmMap.put(Constant.ALARM_UPDATE_CONFIG_STATE_URI,newMap.get(Constant.ALARM_UPDATE_CONFIG_STATE_URI));
                }
                if(alarmMap.get(Constant.ALARM_UPDATE_CONFIG_CONNECT_TIMEOUT) !=null && newMap.get(Constant.ALARM_UPDATE_CONFIG_CONNECT_TIMEOUT)!=null){
                    alarmMap.put(Constant.ALARM_UPDATE_CONFIG_CONNECT_TIMEOUT,Integer.valueOf(newMap.get(Constant.ALARM_UPDATE_CONFIG_CONNECT_TIMEOUT).toString()));
                }
                if(alarmMap.get(Constant.ALARM_UPDATE_CONFIG_INTERVAL_TIME) !=null && newMap.get(Constant.ALARM_UPDATE_CONFIG_INTERVAL_TIME)!=null){
                    alarmMap.put(Constant.ALARM_UPDATE_CONFIG_INTERVAL_TIME,Integer.valueOf(newMap.get(Constant.ALARM_UPDATE_CONFIG_INTERVAL_TIME).toString()));
                }
            }

            fw = new FileWriter(new File(path));
            yaml.dump(oldMap, fw);
            fw.flush();
            result = true;
        } catch (Exception ex) {
            Log.error("updateGcsFactory() error", ex);
        }finally {
            try {
                if(fis != null) {
                    fis.close();
                }
                if(fw != null){
                    fw.close();
                }
            } catch (IOException ex) {
                com.adcc.utility.log.Log.error(getClass().getName(), "close io error", ex);
            }
        }
        return result;
    }

    /**
     * 保存sysAlarm配置信息
     */
    public boolean saveYamlConfig(AlarmFactory alarmFactory) {
        FileWriter fw = null;
        try {
            String path = System.getProperty("user.dir") + File.separator + "conf" + File.separator + "conf.yml";
            fw = new FileWriter(new File(path));
            fw.write(Constant.YML_ROOT_NAME + ":" + "\n");
            fw.write("# sound file\n");
            fw.write("  path: " + alarmFactory.getPath() + "\n");
            fw.write("# get GMS users address\n");
            fw.write("  userUri: " + alarmFactory.getUserUri() + "\n");
            fw.write("# user synchronization time interval\n");
            fw.write("  intervalTime: " + alarmFactory.getIntervalTime() + "\n");
            fw.write("# UDP settings Transport(0:UNICAST, 1:MULTICAST, 2:BROADCAST)\n");
            fw.write("  multiAddress: " + alarmFactory.getMultiAddress() + "\n");
            fw.write("  host: " + alarmFactory.getHost() + "\n");
            fw.write("  port: " + alarmFactory.getPort() + "\n");
            fw.write("  transport: " + alarmFactory.getTransport() + "\n");
            fw.flush();
            return true;
        } catch (Exception ex) {
            com.adcc.utility.log.Log.error(this.getClass().getName(), "saveConfig() error", ex);
            return false;
        } finally {
            if (fw != null) {
                try {
                    fw.close();
                } catch (IOException ex) {
                    com.adcc.utility.log.Log.error(this.getClass().getName(), "close io error", ex);
                    return false;
                }
            }
        }
    }
}
